"use client";

import React, {
  forwardRef,
  RefObject,
  useImperativeHandle,
  useRef,
  useState,
} from "react";
import { type ImageData } from "../../useScrollCanvas";
import gsap from "gsap";
import { SplitText } from "gsap/SplitText";
import { addPx } from "@/utils";

gsap.registerPlugin(SplitText);

export interface AnimatingImageRef {
  startSelectAnimation: (clickedImage: ImageData) => void;
  startDeselectAnimation: (selectedImg: ImageData) => void;
}

interface AnimatingImageProps {
  selectedImage: ImageData | null;
  imgDimensions: { width: number; height: number };
  canvasRef: RefObject<HTMLCanvasElement | null>;
  animationFrameRef: RefObject<number | null>;
  setImageData: React.Dispatch<React.SetStateAction<ImageData[]>>;
  setSelectedImage: React.Dispatch<React.SetStateAction<ImageData | null>>;
  requestRedraw: () => void;
}

const AnimatingImage = forwardRef<AnimatingImageRef, AnimatingImageProps>(
  (props, ref) => {
    const {
      selectedImage,
      imgDimensions,
      canvasRef,
      setImageData,
      setSelectedImage,
      animationFrameRef,
      requestRedraw,
    } = props;

    const animatingImageRef = useRef<HTMLImageElement | null>(null);
    const selectedImageTitleRef = useRef<HTMLImageElement | null>(null);
    const selectedImageDescRef = useRef<HTMLImageElement | null>(null);
    const titleAnimatingTimeListRef = useRef<Array<number>>([]);
    const [animatingImage, setAnimatingImage] = useState<{
      img: ImageData;
      startX: number;
      startY: number;
      targetX: number;
      targetY: number;
      startTime: number;
      currentX: number;
      currentY: number;
    } | null>(null);

    // 开始选中动画
    const startSelectAnimation = (clickedImage: ImageData) => {
      if (animatingImage) return; // 如果正在动画中，忽略

      const rect = canvasRef.current?.getBoundingClientRect();
      if (!rect) return;

      setSelectedImage(clickedImage);
      setTimeout(() => {
        const fontTop = selectedImageTitleRef.current!.parentElement!.style.top;

        gsap.fromTo(
          selectedImageTitleRef.current!.parentElement,
          { top: addPx(fontTop, 30) },
          { top: fontTop, duration: 0.25, delay: 0.05 }
        );

        selectedImageTitleRef.current!.style.opacity = "1";
        const singleText = new SplitText(selectedImageTitleRef.current, {
          type: "chars",
        });
        const timeList = Array.from({ length: 5 }, () => Math.random() * 0.2);
        titleAnimatingTimeListRef.current = timeList;
        singleText.chars.forEach((char, index) => {
          gsap.fromTo(
            char,
            { opacity: 0 },
            {
              opacity: 1,
              duration: 0.25,
              delay: timeList[index] + 0.15,
            }
          );
        });

        gsap.fromTo(
          selectedImageDescRef.current,
          { opacity: 0, letterSpacing: "10px" },
          {
            opacity: 1,
            letterSpacing: "0px",
            duration: 0.25,
            delay: 0.15,
          }
        );
      }, 0);

      // 选中的图片立即变成透明度0，其他图片保持可见准备动画
      setImageData((prevData) =>
        prevData.map((imgData) => ({
          ...imgData,
          // 选中的图片立即变成透明度0，其他图片保持原透明度
          opacity: imgData.index === clickedImage.index ? 0 : imgData.opacity,
        }))
      );

      // 立即触发重绘以显示透明度变化
      requestRedraw();

      // 计算canvas中图片的绝对位置
      const startX = rect.left + clickedImage.x;
      const startY = rect.top + clickedImage.y;

      // 计算目标位置（屏幕中心往上100px）
      const targetX = (window.innerWidth - imgDimensions.width) / 2;
      const targetY = (window.innerHeight - imgDimensions.height) / 2 - 100;

      const animationData = {
        img: clickedImage,
        startX,
        startY,
        targetX,
        targetY,
        startTime: Date.now(),
        currentX: startX,
        currentY: startY,
      };

      setAnimatingImage(animationData);

      // 开始动画
      const animate = () => {
        const elapsed = Date.now() - animationData.startTime;
        const progress = Math.min(elapsed / 500, 1); // 500ms动画时长

        // 使用easeOutCubic缓动函数
        const easeProgress = 1 - Math.pow(1 - progress, 3);
        const currentX = startX + (targetX - startX) * easeProgress;
        const currentY = startY + (targetY - startY) * easeProgress;

        // 其他图片透明度逐渐变为0的动画
        setImageData((prevData) =>
          prevData.map((imgData) => {
            if (imgData.index === clickedImage.index) {
              return imgData; // 选中的图片保持透明度0
            }
            // 其他图片透明度逐渐变为0
            const targetOpacity = 0;
            const currentOpacity = Math.max(1 - easeProgress, targetOpacity);
            return { ...imgData, opacity: currentOpacity };
          })
        );

        // 直接更新DOM位置，避免重新渲染
        if (animatingImageRef.current) {
          animatingImageRef.current.style.left = `${currentX}px`;
          animatingImageRef.current.style.top = `${currentY}px`;
        }

        // 触发canvas重绘以显示透明度变化
        requestRedraw();

        if (progress >= 1) {
          // 动画完成，显示选中状态
          setAnimatingImage(null);
          return;
        }

        animationFrameRef.current = requestAnimationFrame(animate);
      };

      animate();
    };

    // 开始取消选中动画
    const startDeselectAnimation = (selectedImg: ImageData) => {
      if (animatingImage) return; // 如果正在动画中，忽略

      const rect = canvasRef.current?.getBoundingClientRect();
      if (!rect) return;

      // 计算目标位置（canvas中图片的位置）
      const targetX = rect.left + selectedImg.x;
      const targetY = rect.top + selectedImg.y;

      // 计算起始位置（屏幕中心往上100px）
      const startX = (window.innerWidth - imgDimensions.width) / 2;
      const startY = (window.innerHeight - imgDimensions.height) / 2 - 100;

      const animationData = {
        img: selectedImg,
        startX,
        startY,
        targetX,
        targetY,
        startTime: Date.now(),
        currentX: startX,
        currentY: startY,
      };

      // 先清除选中状态，显示动画
      setAnimatingImage(animationData);

      const singleText = new SplitText(selectedImageTitleRef.current, {
        type: "chars",
      });
      const fontTop = selectedImageTitleRef.current!.parentElement!.style.top;

      gsap.fromTo(
        selectedImageTitleRef.current!.parentElement,
        { top: fontTop },
        { top: addPx(fontTop, 30), duration: 0.2 }
      );
      singleText.chars.forEach((char, index) => {
        gsap.fromTo(
          char,
          { opacity: 1 },
          {
            opacity: 0,
            duration: 0.2,
            delay: titleAnimatingTimeListRef.current[index],
          }
        );
      });

      gsap.fromTo(
        selectedImageDescRef.current,
        { opacity: 1, letterSpacing: "10px" },
        {
          opacity: 0,
          letterSpacing: "0px",
          duration: 0.2,
        }
      );

      // 开始动画
      const animate = () => {
        const elapsed = Date.now() - animationData.startTime;
        const progress = Math.min(elapsed / 400, 1); // 400ms动画时长（稍快一些）

        // 使用easeOutCubic缓动函数
        const easeProgress = 1 - Math.pow(1 - progress, 3);
        const currentX = startX + (targetX - startX) * easeProgress;
        const currentY = startY + (targetY - startY) * easeProgress;

        // 同时进行其他图片的透明度恢复动画（逐个显示）
        setImageData((prevData) =>
          prevData.map((imgData) => {
            if (imgData.index === selectedImg.index) {
              return imgData; // 选中的图片不变
            }
            return { ...imgData, opacity: 1 };
          })
        );

        // 直接更新DOM位置，避免重新渲染
        if (animatingImageRef.current) {
          animatingImageRef.current.style.left = `${currentX}px`;
          animatingImageRef.current.style.top = `${currentY}px`;
        }

        // 触发canvas重绘以显示透明度变化
        requestRedraw();

        if (progress >= 1) {
          setSelectedImage(null);
          // 动画完成，清除动画状态
          setAnimatingImage(null);
          // 确保所有图片都完全可见
          setImageData((prevData) =>
            prevData.map((imgData) => ({ ...imgData, opacity: 1 }))
          );
          return;
        }

        animationFrameRef.current = requestAnimationFrame(animate);
      };

      animate();
    };

    useImperativeHandle(ref, () => ({
      startSelectAnimation,
      startDeselectAnimation,
    }));

    // 动画图片组件
    const Comp = () => {
      if (!animatingImage) return null;

      return (
        <>
          {animatingImage.img.img && (
            <img
              ref={animatingImageRef}
              src={animatingImage.img.img.src}
              alt="animating image"
              className="fixed z-[5] pointer-events-none"
              style={{
                left: animatingImage.currentX,
                top: animatingImage.currentY,
                width: `${imgDimensions.width}px`,
                height: `${imgDimensions.height}px`,
                borderRadius: "10px",
              }}
            />
          )}
        </>
      );
    };

    return (
      <>
        <Comp />

        {selectedImage ? (
          <div
            className="absolute top-0 left-0 w-full h-full z-[5]"
            onClick={() =>
              selectedImage && startDeselectAnimation(selectedImage)
            }
          >
            {/* 固定位置的图片和文字容器 */}
            <div
              className="absolute flex flex-col items-center"
              style={{
                left: "50%",
                top: "50%",
                transform: "translate(-50%, calc(-50% - 100px))",
              }}
            >
              {!animatingImage ? (
                <img
                  src={selectedImage.gameData.img}
                  alt="selected image"
                  style={{
                    width: `${imgDimensions.width}px`,
                    height: `${imgDimensions.height}px`,
                    borderRadius: "10px",
                  }}
                />
              ) : (
                // 这是占位用的 懒得去算了 就用这个吧！
                <div
                  style={{
                    width: `${imgDimensions.width}px`,
                    height: `${imgDimensions.height}px`,
                    borderRadius: "10px",
                  }}
                />
              )}

              <div
                className="absolute flex flex-col items-center mt-5"
                style={{
                  top: `${imgDimensions.height}px`,
                }}
              >
                {/* 这里不换行 */}
                <div
                  className="text-4xl font-bold mt-4 text-nowrap opacity-0 tracking-widest"
                  ref={selectedImageTitleRef}
                >
                  {selectedImage.gameData.name}
                </div>
                {/* 这里不换行 */}
                <div
                  className=" mt-4 text-nowrap opacity-0"
                  ref={selectedImageDescRef}
                >
                  {selectedImage.gameData.desc}
                </div>
              </div>
            </div>
          </div>
        ) : null}
      </>
    );
  }
);

export default AnimatingImage;
